package cn.jltx.support;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.MotionEvent;

import java.util.ArrayList;

import cn.jltx.constant.FragmentConstant;
import cn.jltx.helper.FragmentLifecycleCallbacks;
import cn.jltx.helper.LifecycleHelper;
import cn.jltx.utils.XqLog;

/**
 * @author jltxseo
 *         Created by junlintianxia on 2017/04/12.
 */

public class SupportAppCompatActivity extends AppCompatActivity implements ISupport{

    private final String TAG = SupportAppCompatActivity.class.getSimpleName();
    private FragmentImpl fragmentImpl;

    private LifecycleHelper mLifecycleHelper;
    private ArrayList<FragmentLifecycleCallbacks> mFragmentLifecycleCallbacks;

    // 防抖动 是否可以点击
    private boolean mFragmentClickable = true;
    //出栈多个Fragment时不做动画
    boolean mPopMultipleNoAnim = false;

    public void registerFragmentLifecycleCallbacks(FragmentLifecycleCallbacks callback) {
        synchronized (this) {
            if (mFragmentLifecycleCallbacks == null) {
                mFragmentLifecycleCallbacks = new ArrayList<>();
                mLifecycleHelper = new LifecycleHelper(mFragmentLifecycleCallbacks);
            }
            if(!mFragmentLifecycleCallbacks.contains(callback)){
                mFragmentLifecycleCallbacks.add(callback);
            }

        }
    }

    public void unregisterFragmentLifecycleCallbacks(FragmentLifecycleCallbacks callback) {
        synchronized (this) {
            if (mFragmentLifecycleCallbacks != null) {
                mFragmentLifecycleCallbacks.remove(callback);
            }
        }
    }

    @Override
    public void loadRootFragment(int containerId, SupportFragment to) {
        fragmentImpl.loadRootFragment(getSupportFragmentManager(),containerId,to);
    }

    @Override
    public void loadMultipleRootFragment(int containerId, SupportFragment... toFragments) {
        loadMultipleRootFragment(containerId,0,toFragments);
    }

    /**
     *
     * @param containerId
     * @param showPosition
     * @param toFragments
     */
    @Override
    public void loadMultipleRootFragment(int containerId, int showPosition, SupportFragment... toFragments) {
        fragmentImpl.loadMutipleRootFragment(getSupportFragmentManager(),containerId,showPosition,toFragments);
    }

    @Override
    public void startFragment(SupportFragment toFragment) {
        fragmentImpl.dispatchStartTransaction(getSupportFragmentManager(),getTopFragment(),toFragment, FragmentConstant.TYPE_ADD);
    }

    @Override
    public void startFragmentWithPop(SupportFragment toFragment) {
        fragmentImpl.dispatchStartTransaction(getSupportFragmentManager(),getTopFragment(),toFragment,FragmentConstant.TYPE_ADD_WITH_POP);
    }

    @Override
    public void popFragmentTo(Class<?> fragmentClass, boolean includeSelf, Runnable afterPopTransactionRunnable) {
        popFragmentTo(fragmentClass.getName(),includeSelf,afterPopTransactionRunnable);
    }

    @Override
    public void popFragmentTo(String fragmentTag, boolean includeSelf, Runnable afterPopTransactionRunnable) {
        fragmentImpl.popFragmentTo(fragmentTag,includeSelf,afterPopTransactionRunnable,getSupportFragmentManager());

    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        fragmentImpl = getFragmentImpl();
    }

    @Override
    public FragmentImpl getFragmentImpl() {
        if (fragmentImpl == null) {
            fragmentImpl = new FragmentImpl();
        }
        fragmentImpl.attachActivity(this);
        return fragmentImpl;
    }

    @Override
    public <T extends SupportFragment> T findFragment(Class<T> fragmentClass) {
        return fragmentImpl.findStackFragment(getSupportFragmentManager(),fragmentClass,null);
    }

    @Override
    public <T extends SupportFragment> T findFragment(String fragmentTag) {
        fragmentImpl.checkNotNull(fragmentTag, "tag == null");
        return fragmentImpl.findStackFragment(getSupportFragmentManager(),null,fragmentTag);
    }

    @Override
    public void showHideFragment(SupportFragment showFragment) {
        showHideFragment(showFragment,null);
    }

    @Override
    public void showHideFragment(SupportFragment showFragment, SupportFragment hideFragment) {
        fragmentImpl.showHideFragment(getSupportFragmentManager(),showFragment,hideFragment);
    }

    @Override
    public void replaceLoadRootFragment(int containerId, SupportFragment toFragment, boolean addToBack) {
        fragmentImpl.replaceLoadRootTransaction(getSupportFragmentManager(),containerId,toFragment,addToBack);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mFragmentLifecycleCallbacks != null) {
            mFragmentLifecycleCallbacks.clear();
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        if ((keyCode == KeyEvent.KEYCODE_BACK)) {
            // 这里是防止动画过程中，按返回键取消加载Fragment
            if (!mFragmentClickable) {
                setFragmentClickable(true);
                XqLog.d(TAG,"onKeyDown"+mFragmentClickable);
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        XqLog.d(TAG,"onKeyUp");
        return super.onKeyUp(keyCode, event);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        XqLog.d(TAG,"dispatchTouchEvent=>"+mFragmentClickable);
        if(!mFragmentClickable){
            return true;
        }else {
            return super.dispatchTouchEvent(ev);
        }
    }

    @Override
    final public void onBackPressed() {
        // 这里是防止动画过程中，按返回键取消加载Fragment
        if (!mFragmentClickable) {
            setFragmentClickable(true);
            XqLog.d(TAG,"onBackPressed=>"+mFragmentClickable);
        }
        // 获取activeFragment:即从栈顶开始 状态为show的那个Fragment
        SupportFragment activeFragment = fragmentImpl.getActiveFragment(null, getSupportFragmentManager());
        if (fragmentImpl.dispatchBackPressedEvent(activeFragment)) return;
        onBackPressedSupport();

    }

    public void onBackPressedSupport() {
        if(isRootInTop()){
            pop();
        }else {
            finish();
        }
    }

    public boolean isRootInTop(){
        if(getSupportFragmentManager().getBackStackEntryCount() > 1){
            return true;
        }else {
            return false;
        }
    }

    @Override
    public SupportFragment getTopFragment() {
        return fragmentImpl.getTopFragment(getSupportFragmentManager());
    }

    /**
     * 当抛该异常："Can not perform this action after onSaveInstanceState!"时（不会crash，仅警告），会回调该方法
     */
    public void onExceptionAfterOnSaveInstanceState(Exception e) {
    }

    /**
     * 依次出栈
     */
    @Override
    public void pop() {
        fragmentImpl.back(getSupportFragmentManager());
    }

    void preparePopMultiple() {
        mPopMultipleNoAnim = true;
    }

    void popFinish() {
        mPopMultipleNoAnim = false;
    }

    /**
     * 防抖动(防止点击速度过快)
     */
    void setFragmentClickable(boolean clickable) {
        mFragmentClickable = clickable;
    }

    void dispatchFragmentLifecycle(int lifecycle, SupportFragment fragment, Bundle bundle, boolean visible) {
        if (mLifecycleHelper == null) return;
        mLifecycleHelper.dispatchLifecycle(lifecycle, fragment, bundle, visible);
    }

}
